#!/bin/sh

###################################################################################################
# THIS MODULE INCLUDES ALL ACTIONS INTENDED TO ISOLATE DOTFILES OR CONTAINERIZE INSTALLED APPIMAGES
###################################################################################################

# Set a dedicated .home directory for a selected AppImage
_home() {
	if [ ! -d "$APPSPATH"/"$arg" ]; then
		echo " ERROR: \"$arg\" is not installed" || return
	elif [ -d "$APPSPATH/$arg/$arg.home" ]; then
		echo " ERROR: \"$arg\" already contains a home dir"
	elif ! strings -d "$APPSPATH/$arg/$arg" | grep -- '--appimage-extract' 1>/dev/null; then
		echo " ERROR: \"$arg\" is NOT an AppImage"
	else
		mkdir "$APPSPATH/$arg/$arg.home" || return
		echo ' $HOME set to '"$APPSPATH/$arg/$arg.home for $arg"''
	fi
}

_config() {
	if [ ! -d "$APPSPATH"/"$arg" ]; then
		echo " ERROR: \"$arg\" is not installed" || return
	elif [ -d "$APPSPATH/$arg/$arg.config" ]; then
		echo " ERROR: \"$arg\" already contains a config dir"
	elif ! strings -d "$APPSPATH/$arg/$arg" | grep -- '--appimage-extract' 1>/dev/null; then
		echo " ERROR: \"$arg\" is NOT an AppImage"
	else
		mkdir "$APPSPATH/$arg/$arg.config" || return
		echo ' $XDG_CONFIG_HOME set to '"$APPSPATH/$arg/$arg.config for $arg"''
	fi
}

if [ "$1" = "--disable-sandbox" ]; then
	[ -z "$2" ] && echo "You need to specify the application to unsandbox, aborting" && exit 1
	grep "aisap-am sandboxing script" "$(command -v "$2")" >/dev/null 2>&1 || { echo "Not a sandboxed application, aborting"; exit 1; }
	"$2" --disable-sandbox
	exit 0
fi 

case "$1" in
  '--sandbox')

	# This script makes it easy to sandbox AppImages installed with AppMan or AM
	# The default location for the sandboxed homes is at $HOME/.local/am-sandboxes
	# But that location can be changed by setting the $SANDBOXDIR env variable
	# aisap: https://github.com/mgord9518/aisap

	[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
	while [ -n "$1" ]; do
		# Safety checks
		if ! test -f "$APPSPATH/$2/remove"; then
			echo " '$2' is not a valid argument or is not installed."; exit
		elif [ "$2" = "aisap" ]; then
			echo " Error: You can't sandbox aisap"; exit 1
		elif ! command -v aisap 1>/dev/null; then
			printf '\n%s\n\n' " Error: You need aisap for this script work"
			read -p " ◆ DO YOU WISH TO INSTALL AISAP? Install size <5 MIB, (Y/n)?: " yn
			if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
				printf '\n%s\n\n' "Installation aborted"; exit 1
			fi
			$AMCLIPATH -i aisap >/dev/null 2>&1
			command -v aisap 1>/dev/null && printf '\n%s\n\n' " aisap installed successfully" || exit 1
		fi

		# Set variables
		if [ "$AMCLI" = am ]; then
			TARGET="/usr/local/bin/$2"
		else
			BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}"
			mkdir -p "$BINDIR"
			TARGET="$BINDIR/$2"
		fi
		APPIMAGEPATH="$APPSPATH/$2"
		APPIMAGE="$APPIMAGEPATH/$2"

		# Check if TARGET is an AppImage or was already sandboxed
		if grep "aisap-am" "$TARGET" >/dev/null 2>&1; then
			echo " $2 is already sandboxed!"; exit 1
		elif ! strings -d "$APPIMAGE" | grep -- '--appimage-extract' 1>/dev/null; then
			echo " $TARGET doesn't look like an AppImage, aborting"; exit 1
		fi

		# Check if we are using AM or AppMan
		printf '\n%s\n' " Making aisap script for \"$(echo "$AMCLI" | tr a-z A-Z)\"..."

		[ -z "$AMCACHEDIR" ] && exit 1
		rm -Rf "$AMCACHEDIR/sandbox-scripts"
		mkdir -p "$AMCACHEDIR/sandbox-scripts"

		# Get xdg variables
		XDG_DESKTOP_DIR="$(xdg-user-dir DESKTOP 2>/dev/null)"
		XDG_DOCUMENTS_DIR="$(xdg-user-dir DOCUMENTS 2>/dev/null)"
		XDG_DOWNLOAD_DIR="$(xdg-user-dir DOWNLOAD 2>/dev/null)"
		XDG_MUSIC_DIR="$(xdg-user-dir MUSIC 2>/dev/null)"
		XDG_PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null)"
		XDG_VIDEOS_DIR="$(xdg-user-dir VIDEOS 2>/dev/null)"

		# Unset the xdg variable if it equals to $HOME
		if [ "$XDG_DESKTOP_DIR" = "$HOME" ] || [ "$XDG_DESKTOP_DIR" = "$HOME/" ]; then XDG_DESKTOP_DIR=""; fi
		if [ "$XDG_DOCUMENTS_DIR" = "$HOME" ] || [ "$XDG_DOCUMENTS_DIR" = "$HOME/" ]; then XDG_DOCUMENTS_DIR=""; fi
		if [ "$XDG_DOWNLOAD_DIR" = "$HOME" ] || [ "$XDG_DOWNLOAD_DIR" = "$HOME/" ]; then XDG_DOWNLOAD_DIR=""; fi
		if [ "$XDG_MUSIC_DIR" = "$HOME" ] || [ "$XDG_MUSIC_DIR" = "$HOME/" ]; then XDG_MUSIC_DIR=""; fi
		if [ "$XDG_PICTURES_DIR" = "$HOME" ] || [ "$XDG_PICTURES_DIR" = "$HOME/" ]; then XDG_PICTURES_DIR=""; fi
		if [ "$XDG_VIDEOS_DIR" = "$HOME" ] || [ "$XDG_VIDEOS_DIR" = "$HOME/" ]; then XDG_VIDEOS_DIR=""; fi

		cat <<-"HEREDOC" >> "$AMCACHEDIR/sandbox-scripts/$2"
		#!/bin/sh

		# aisap-am sandboxing script
		# Run this script with --disable-sandbox to do what the flag name implies

		# Dependency check
		if ! command -v aisap 1>/dev/null; then
			echo "You need aisap for this to work"
			notify-send -u critical "Sandbox error; Missing aisap dependency!"
			exit 1
		fi

		# Set variables and create sandboxed dir.
		APPEXEC=DUMMY
		chmod a-x "$APPEXEC" # Prevents accidental launch of the app outside the sandbox
		APPNAME="$(echo "$APPEXEC" | awk -F "/" '{print $NF}')"
		SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}"
		DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}"
		CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}"
		CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}"
		DBUS="$(ls /tmp/dbus* 2>/dev/null | head -1)" # Prevents crash if there is multiple dbus

		XDG_DESKTOP_DIR="$(xdg-user-dir DESKTOP 2>/dev/null)"
		XDG_DOCUMENTS_DIR="$(xdg-user-dir DOCUMENTS 2>/dev/null)"
		XDG_DOWNLOAD_DIR="$(xdg-user-dir DOWNLOAD 2>/dev/null)"
		XDG_GAMES_DIR="$(xdg-user-dir GAMES 2>/dev/null)"
		XDG_MUSIC_DIR="$(xdg-user-dir MUSIC 2>/dev/null)"
		XDG_PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null)"
		XDG_VIDEOS_DIR="$(xdg-user-dir VIDEOS 2>/dev/null)"

		if [ "$XDG_DESKTOP_DIR" = "$HOME" ] || [ "$XDG_DESKTOP_DIR" = "$HOME/" ]; then XDG_DESKTOP_DIR=""; fi
		if [ "$XDG_DOCUMENTS_DIR" = "$HOME" ] || [ "$XDG_DOCUMENTS_DIR" = "$HOME/" ]; then XDG_DOCUMENTS_DIR=""; fi
		if [ "$XDG_DOWNLOAD_DIR" = "$HOME" ] || [ "$XDG_DOWNLOAD_DIR" = "$HOME/" ]; then XDG_DOWNLOAD_DIR=""; fi
		if [ "$XDG_GAMES_DIR" = "$HOME" ] || [ "$XDG_GAMES_DIR" = "$HOME/" ]; then XDG_GAMES_DIR=""; fi
		if [ "$XDG_MUSIC_DIR" = "$HOME" ] || [ "$XDG_MUSIC_DIR" = "$HOME/" ]; then XDG_MUSIC_DIR=""; fi
		if [ "$XDG_PICTURES_DIR" = "$HOME" ] || [ "$XDG_PICTURES_DIR" = "$HOME/" ]; then XDG_PICTURES_DIR=""; fi
		if [ "$XDG_VIDEOS_DIR" = "$HOME" ] || [ "$XDG_VIDEOS_DIR" = "$HOME/" ]; then XDG_VIDEOS_DIR=""; fi

		# Try to find the right name of the app xdg directories, as sometimes it is not the same as $APPNAME
		APPDATA=$( ls "$DATADIR" | grep -i "$APPNAME" | head -1 )
		APPCONF=$( ls "$CONFIGDIR" | grep -i "$APPNAME" | head -1 ) 

		mkdir -p "$SANDBOXDIR/$APPNAME"
		if [ "$1" = "--disable-sandbox" ]; then
			APPIMAGEPATH="$(echo ${APPEXEC%/*})"
			printf '\n%s' " Giving exec permissions back to $APPEXEC..."
			chmod a+x "$APPEXEC" || exit 1
			printf '\n%s' " Patching $APPIMAGEPATH/AM-updater to give permissions back..."
			sed -i 's|chmod a-x|chmod a+x|g' "$APPIMAGEPATH/AM-updater" || exit 1
			THISFILE="$(realpath "$0")"
			printf '\n%s\n' " Replacing $THISFILE with a link to the AppImage..."
			SUDO ln -sf "$APPEXEC" "$THISFILE" || exit 1
			printf '\033[32m\n%s\n\n' " $APPEXEC successfully unsandboxed!"
			exit 0
		fi
		if [ -z "$APPNAME" ]; then exit 1; fi

		# Start at sandboxed home
		# Edit below this to add or remove access to parts of the system
		exec aisap --trust-once --level 2 \
		--data-dir "$SANDBOXDIR/$APPNAME" \
		--add-file "$DATADIR/${APPDATA:-$APPNAME}":rw \
		--add-file "$DATADIR"/themes \
		--add-file "$DATADIR"/icons \
		--add-file "$CONFIGDIR/${APPCONF:-$APPNAME}":rw \
		--add-file "$CONFIGDIR"/dconf \
		--add-file "$CONFIGDIR"/gtk3.0 \
		--add-file "$CONFIGDIR"/gtk4.0 \
		--add-file "$CONFIGDIR"/kdeglobals \
		--add-file "$CONFIGDIR"/qt5ct \
		--add-file "$CONFIGDIR"/qt6ct \
		--add-file "$CONFIGDIR"/Kvantum \
		--add-file "$HOME"/.local/lib \
		--add-file /usr/share \
		--rm-file /path/to/nothing \
		--rm-file "${XDG_DESKTOP_DIR:-~/Desktop}" \
		--rm-file "${XDG_DOCUMENTS_DIR:-~/Documents}" \
		--rm-file "${XDG_DOWNLOAD_DIR:-~/Downloads}" \
		--rm-file "${XDG_GAMES_DIR:-~/Games}" \
		--rm-file "${XDG_MUSIC_DIR:-~/Music}" \
		--rm-file "${XDG_PICTURES_DIR:-~/Pictures}" \
		--rm-file "${XDG_VIDEOS_DIR:-~/Videos}" \
		--add-file /var/lib/dbus \
		--add-file "${DBUS:-/tmp/dbus}" \
		--add-socket pulseaudio \
		--add-socket dbus \
		--add-socket network \
		--add-socket x11 \
		--add-socket wayland \
		--add-device dri -- \
		"$APPEXEC" "$@"
		HEREDOC
		printf '\033[33m\n'
		read -p " Do you want configure access to directories? (Y/n): " yn
		if ! echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
			printf '\033[36m\n'
			read -p " Allow $2 access to $(echo ${XDG_DESKTOP_DIR:-~/Desktop} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_DESKTOP_DIR:-~/Desktop}"|--add-file "${XDG_DESKTOP_DIR:-~/Desktop}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_DOCUMENTS_DIR:-~/Documents} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_DOCUMENTS_DIR:-~/Documents}"|--add-file "${XDG_DOCUMENTS_DIR:-~/Documents}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_DOWNLOAD_DIR:-~/Downloads} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_DOWNLOAD_DIR:-~/Downloads}"|--add-file "${XDG_DOWNLOAD_DIR:-~/Downloads}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_GAMES_DIR:-~/Games} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_GAMES_DIR:-~/Games}"|--add-file "${XDG_GAMES_DIR:-~/Games}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_MUSIC_DIR:-~/Music} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_MUSIC_DIR:-~/Music}"|--add-file "${XDG_MUSIC_DIR:-~/Music}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_PICTURES_DIR:-~/Pictures} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_PICTURES_DIR:-~/Pictures}"|--add-file "${XDG_PICTURES_DIR:-~/Pictures}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			read -p " Allow $2 access to $(echo ${XDG_VIDEOS_DIR:-~/Videos} | sed "s|$HOME|~|g")? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				sed -i 's|--rm-file "${XDG_VIDEOS_DIR:-~/Videos}"|--add-file "${XDG_VIDEOS_DIR:-~/Videos}":rw|g' "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			sleep 0.5
			printf '\033[31m'
			read -p " Allow $2 access to a specific directory? (y/N): " yn
			if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
				printf '\n%s\n' "   Warning: giving access to all of $HOME or / and similar is not safe"
				printf '%s\n\033[33m' "   Also aisap might not let the application start when such paths are given"
				printf '\n%s\n' "   Type the path to the directory"
				read -p "   Example /media/external-drive or ~/Backups: " NEWDIR
				[ -z "$NEWDIR" ] && printf '\033[31m\n%s\n' "   No path given, aborting" && exit 1
				if [ "$NEWDIR" = '$HOME' ] || [ "$NEWDIR" = '$HOME/' ] || [ "$NEWDIR" = "$HOME" ] || [ "$NEWDIR" = "$HOME/" ] || [ "$NEWDIR" = "/" ] \
				|| [ "$NEWDIR" = "~" ] || [ "$NEWDIR" = "~/" ] || [ "$NEWDIR" = "/home" ] || [ "$NEWDIR" = "/home" ] || [ "$NEWDIR" = "/home/" ]; then
					notify-send -u critical "DO YOU WANT THE FBI TO GET YA?"
					printf '\033[31m%s\n' && read -p "   SPOOKY LOCATION DETECTED! ARE YOU SURE? IF SO TYPE \"YES\": "
					[ $YES != "YES" ] && echo "That's not a \"YES\", aborting" && exit 1
				fi			
				printf '\n%s\n' "   Giving access to \"$NEWDIR\"..."
				sed -i "s|--rm-file /path/to/nothing|--add-file $NEWDIR:rw|g" "$AMCACHEDIR/sandbox-scripts/$2" || exit 1
			fi
			printf '\n\033[32m%s\n' " User directories access configured successfully!"
		fi

		chmod a+x "$AMCACHEDIR/sandbox-scripts/$2" && sed -i "s|DUMMY|$APPIMAGE|g; s|SUDO |$SUDOCOMMAND |g" "$AMCACHEDIR/sandbox-scripts/$2" || exit 1

		# Remove the exec permission from the AppImage and its updater for better safety™
		$SUDOCOMMAND rm -f "$TARGET" && chmod a-x "$APPIMAGE" &&
		sed -i 's|chmod a+x|chmod a-x|g' "$APPIMAGEPATH/AM-updater" || exit 1

		# Put sandbox script in the place of the appimage symlink
		$SUDOCOMMAND mv "$AMCACHEDIR/sandbox-scripts/$2" "$TARGET" && rmdir "$AMCACHEDIR/sandbox-scripts" || exit 1

		printf '\n%s\n' " \"$2\" successfully sandboxed!"
		printf '\n\033[0m%s\n' " The app will be sandboxed in \"${SANDBOXDIR:-$HOME/.local/am-sandboxes}\" once launched"
		printf '\n%s\n' " This location can be moved by setting the 'SANDBOXDIR' env variable"
		printf '\n%s\n' " --------------------------------------------------------------------------"
		printf '\n\033[33m%s\n' " Use the --disable-sandbox flag if you want to revert the changes"
		printf '\n\033[0m%s' " In this case that is:"
		printf '\033[33m%s\033[36m\n\n' " $2 --disable-sandbox"
		_remove_info_files
		exit 0
	done

	shift
	;;

  '-H'|'--home')
	[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
	while [ -n "$1" ]; do
		rm -f "$AMCACHEDIR/home-args"
		echo "$@" | tr ' ' '\n' >> "$AMCACHEDIR/home-args" && echo STOP >> "$AMCACHEDIR/home-args"
		ARGS=$(tail -n +2 "$AMCACHEDIR"/home-args)
		for arg in $ARGS; do
			if [ "$arg" = STOP ]; then
				exit 0
			else
				_home
			fi
		done
	done
	;;

  '-C'|'--config')
	[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
	while [ -n "$1" ]; do
		rm -f "$AMCACHEDIR/config-args"
		echo "$@" | tr ' ' '\n' >> "$AMCACHEDIR/config-args" && echo STOP >> "$AMCACHEDIR/config-args"
		ARGS=$(tail -n +2 "$AMCACHEDIR"/config-args)
		for arg in $ARGS; do
			if [ "$arg" = STOP ]; then
				exit 0
			else
				_config
			fi
		done
	done
	;;
esac
